use std::char;

use crate::token::token;

#[derive(Debug)]
pub struct Lexer {
    pub input: String,
    pub position: usize,     // 输入的字符串中的当前位置(指向当前字符)
    pub readPosition: usize, // 输入的字符串中的当前读取位置(指向当前字符串之后的一个字符(ch))
    pub ch: char,            // 当前正在查看的字符
}

impl Lexer {
    pub fn new(input: String) -> Lexer {
        let mut l = Lexer {
            input: input,
            position: 0,
            readPosition: 0,
            ch: '0',
        };
        l.readChar();
        l
    }
    // 读取词法单元
    fn readChar(&mut self) {
        if self.readPosition >= self.input.len() {
            self.ch = '0';
        } else {
            // 读取
            self.ch = self.input.as_bytes()[self.readPosition] as char;
        }
        // 前移
        self.position = self.readPosition;
        self.readPosition += 1;
    }
    // 根据当前的ch创建词法单元
    pub fn NextToken(&mut self) -> token::Token {
        let tok: token::Token;

        // 跳过空格
        self.skipWhitespace();

        tok = match self.ch {
            '=' => newToken(token::TokenType::ASSIGN, self.ch),
            ';' => newToken(token::TokenType::SEMICOLON, self.ch),
            '(' => newToken(token::TokenType::LPAREN, self.ch),
            ')' => newToken(token::TokenType::RPAREN, self.ch),
            ',' => newToken(token::TokenType::COMMA, self.ch),
            '+' => newToken(token::TokenType::PLUS, self.ch),
            '{' => newToken(token::TokenType::LBRACE, self.ch),
            '}' => newToken(token::TokenType::RBRACE, self.ch),
            '0' => token::Token {
                Literal: String::from(""),
                Type: token::TokenType::EOF,
            },
            _ => {
                if isLetter(self.ch) {
                    let literal = self.readIndentifier();
                    return token::Token {
                        Literal: literal.clone(),
                        Type: token::LookupIdent(&literal),
                    };
                } else if isDigit(self.ch) {
                    let literal = self.readNumber();
                    return token::Token {
                        Literal: literal.clone(),
                        Type: token::TokenType::INT,
                    };
                } else {
                    return token::Token {
                        Literal: String::from(""),
                        Type: token::TokenType::ILLEGAL,
                    };
                }
            }
        };

        self.readChar();
        tok
    }
    // 读取字母(标识符/关键字)
    fn readIndentifier(&mut self) -> String {
        let position = self.position;
        loop {
            if isLetter(self.ch) {
                // 如果接下来还有字母,就一直移动指针到不是字母
                self.readChar();
                continue;
            }
            break;
        }
        self.input[position..self.position].to_string()
    }
    // 跳过空格
    fn skipWhitespace(&mut self) {
        loop {
            if self.ch == ' ' || self.ch == '\t' || self.ch == '\n' || self.ch == '\r' {
                self.readChar();
                continue;
            }
            break;
        }
    }
    // 读取数字
    fn readNumber(&mut self) -> String {
        // 记录起始位置
        let position = self.position;
        loop {
            if isDigit(self.ch) {
                self.readChar();
                continue;
            }
            break;
        }
        self.input[position..self.position].to_string()
    }
}

// 创建词法单元
pub fn newToken(tokenType: token::TokenType, ch: char) -> token::Token {
    token::Token {
        Type: tokenType,
        Literal: String::from(ch),
    }
}

// 判断是否是字母
fn isLetter(ch: char) -> bool {
    'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_'
}

// 判断是否是数字
fn isDigit(ch: char) -> bool {
    '0' <= ch && ch <= '9'
}
